/**
 * @file SingleTracker.cpp
 * @author enemy1205 (enemy1205@qq.com)
 * @date 2021-09-02
 */
#include "SingleTracker.h"
/**
 * @brief 构造函数
 * @param video_path 视频路径
 * @param i 模式选择
 */
SingleTracker::SingleTracker(const string &video_path, int i) {
    VC.open(video_path);
//选择跟踪器类别
    if (trackerType == "BOOSTING") {
        LE_tracker = legacy::TrackerBoosting::create();
        legacy = true;
    }
    if (trackerType == "MIL")
        tracker = TrackerMIL::create();
    if (trackerType == "KCF")
        tracker = TrackerKCF::create();
    if (trackerType == "TLD") {
        LE_tracker = legacy::TrackerTLD::create();
        legacy = true;
    }
    if (trackerType == "MEDIANFLOW") {
        LE_tracker = legacy::TrackerMedianFlow::create();
        legacy = true;
    }
    if (trackerType == "CSRT")
        tracker = TrackerCSRT::create();
    if (trackerType == "MOSSE") {
        LE_tracker = legacy::TrackerMOSSE::create();
        legacy = true;
    }
}

/**
 * @brief 构造函数，默认模式
 * @param video_path  视频路径
 */
SingleTracker::SingleTracker(const string &video_path) {
    VC.open(video_path);
//选择跟踪器类别
    trackerType = trackerTypes[2];
    if (trackerType == "BOOSTING") {
        LE_tracker = legacy::TrackerBoosting::create();
        legacy = true;
    }
    if (trackerType == "MIL")
        tracker = TrackerMIL::create();
    if (trackerType == "KCF")
        tracker = TrackerKCF::create();
    if (trackerType == "TLD") {
        LE_tracker = legacy::TrackerTLD::create();
        legacy = true;
    }
    if (trackerType == "MEDIANFLOW") {
        LE_tracker = legacy::TrackerMedianFlow::create();
        legacy = true;
    }
    if (trackerType == "CSRT")
        tracker = TrackerCSRT::create();
    if (trackerType == "MOSSE") {
        LE_tracker = legacy::TrackerMOSSE::create();
        legacy = true;
    }

}
/**
 * @brief 运行主程序
 * @note 部分算法移入了legacy::Tracker,且仅支持Rect2d ,Tracker仅支持Rect2i
 */
void SingleTracker::run() {
    // Exit if video is not opened 如果没有视频文件
    if (!VC.isOpened()) {
        cout << "Could not read video file" << endl;
    }

    // Read first frame 读图
    Mat frame;
    bool ok =VC.read(frame);
    if (legacy) {
        // Define initial boundibg box 初始检测框
        Rect2d bbox;
        // Uncomment the line below to select a different bounding box 手动在图像上画矩形框
        cout<<"选中后按下SPACE"<<endl;
        bbox = selectROI(frame, false);

        // Display bounding box 展示画的2边缘框
        rectangle(frame, bbox, Scalar(255, 0, 0), 2, 1);
        imshow("Tracking", frame);

        //跟踪器初始化
        LE_tracker->init(frame, bbox);

        while (VC.read(frame)) {
            // Start timer 开始计时
            double timer = (double) getTickCount();

            // Update the tracking result 跟新跟踪器算法
            bool ok = LE_tracker->update(frame, bbox);

            // Calculate Frames per second (FPS) 计算FPS
            float fps = getTickFrequency() / ((double) getTickCount() - timer);

            if (ok) {
                // Tracking success : Draw the tracked object 如果跟踪到目标画框
                rectangle(frame, bbox, Scalar(255, 0, 0), 2, 1);
            } else {
                // Tracking failure detected. 没有就输出跟踪失败
                putText(frame, "跟踪失败", Point(100, 80), FONT_HERSHEY_SIMPLEX, 0.75,
                        Scalar(0, 0, 255),
                        2);
            }

            // Display tracker type on frame 展示检测算法类型
            putText(frame, trackerType + " Tracker", Point(100, 20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(50, 170, 50),
                    2);

            // Display FPS on frame 表示FPS
            putText(frame, "FPS : " + to_string(int(fps)), Point(100, 50), FONT_HERSHEY_SIMPLEX, 0.75,
                    Scalar(50, 170, 50),
                    2);

            // Display frame.
            imshow("Tracking", frame);

            // Exit if ESC pressed.
            int k = waitKey(33);
            if (k == 27) {
                break;
            }
        }
    } else {
        // Define initial boundibg box 初始检测框
        Rect2i bbox;
        // Uncomment the line below to select a different bounding box 手动在图像上画矩形框
        cout<<"选中后按下SPACE"<<endl;
        bbox = selectROI(frame, false);
        // Display bounding box 展示画的2边缘框
        rectangle(frame, bbox, Scalar(255, 0, 0), 2, 1);
        imshow("Tracking", frame);
        //跟踪器初始化
        tracker->init(frame, bbox);

        while (VC.read(frame)) {
            // Start timer 开始计时
            double timer = (double) getTickCount();

            // Update the tracking result 跟新跟踪器算法
            bool ok = tracker->update(frame, bbox);

            // Calculate Frames per second (FPS) 计算FPS
            float fps = getTickFrequency() / ((double) getTickCount() - timer);

            if (ok) {
                // Tracking success : Draw the tracked object 如果跟踪到目标画框
                rectangle(frame, bbox, Scalar(255, 0, 0), 2, 1);
            } else {
                // Tracking failure detected. 没有就输出跟踪失败
                putText(frame, "跟踪失败", Point(100, 80), FONT_HERSHEY_SIMPLEX, 0.75,
                        Scalar(0, 0, 255),
                        2);
            }

            // Display tracker type on frame 展示检测算法类型
            putText(frame, trackerType + " Tracker", Point(100, 20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(50, 170, 50),
                    2);

            // Display FPS on frame 表示FPS
            putText(frame, "FPS : " + to_string(int(fps)), Point(100, 50), FONT_HERSHEY_SIMPLEX, 0.75,
                    Scalar(50, 170, 50),
                    2);

            // Display frame.
            imshow("Tracking", frame);

            // Exit if ESC pressed.
            int k = waitKey(33);
            if (k == 27) {
                break;
            }
        }
    }
}